//
//  EditVideoViewController.m
//  OntheRoadV4
//
//  Created by ZhangYanhua on 15/3/3.
//  Copyright (c) 2015年 EricHuang. All rights reserved.
//

#import "EditVideoViewController.h"
#import "MBProgressHUD.h"
#import <QWToast/QWToast.h>
#import "QWImageMangerConfig.h"
#import "TRSDialView.h"
#import <Photos/Photos.h>

#define VIDEO_THUMBNAIL_PREFETCH_COUNT      100
#define THUMBNAIL_VIEW_SECTION_INSET        (D_PIXELS >= 1241.0f ? 27.0f : (D_PIXELS >= 749.0f ? 30.0f : 25.0f))

#define THUMBNAIL_ITEM_WIDTH                64.0f
#define THUMBNAIL_ITEM_TOP_INSET            13.0f

@interface EditVideoViewController () {
    id videoProgressObserver;
    id videoEndObserver;
    
}

@property (nonatomic, strong) ImageAsset *curAsset;

@property (nonatomic, strong) AVAsset *avAsset;
@property (nonatomic, strong) AVPlayer *player;
@property (nonatomic, strong) AVPlayerLayer *playerLayer;

@property (nonatomic, strong) AVAssetImageGenerator *generator;

@property (nonatomic, strong) NSArray *thumbnailTimes;

@property (nonatomic, strong) NSOperationQueue *mainQueue;

@property (nonatomic, strong) NSMutableDictionary *operationRunning;
@property (nonatomic, strong) NSMutableDictionary *thumbnailCache;

@property (nonatomic, strong) TRSDialView *dialView;

@property (nonatomic, strong) SelectVideoClipView *clipView;

@property (nonatomic, assign) CGFloat PtPerSecond;
@property (nonatomic, assign) CMTime beginTime;
@property (nonatomic, assign) CMTime endTime;

@property (nonatomic, strong) EditVideoHelpers *trimVideoHelper;

@property (nonatomic, strong) ACNavBarDrawer *toast;

@property (nonatomic, strong) UIView *progressView;

@end

@implementation EditVideoViewController

- (void)dealloc
{
    [self removeVideoObservers];
    [[NSNotificationCenter defaultCenter] removeObserver:self];

    [self.mainQueue cancelAllOperations];
}

-(id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:[QWImageMangerConfig baseBundle]];
    if (self)
    {
        
    }
    return self;
}

- (id)initWithAsset:(ImageAsset *)imgAsset
{
    self = [super init];
    if (self) {
        if (imgAsset.asset) {
            _curAsset = imgAsset;
          
            if ([imgAsset.asset isKindOfClass:[ALAsset class]])
            {
                _avAsset = [AVAsset assetWithURL:[imgAsset.asset assetURL]];
            }
            
        }
    }
    return self;
}



-(void)handleAftergetAVAsset
{
    _player = [AVPlayer playerWithPlayerItem:[AVPlayerItem playerItemWithAsset:_avAsset]];
    _player.actionAtItemEnd = AVPlayerActionAtItemEndNone;
    _playerLayer = [AVPlayerLayer playerLayerWithPlayer:_player];
    _playerLayer.videoGravity = AVLayerVideoGravityResizeAspect;
    
    _beginTime = CMTimeMake(0, 1);
    _endTime = CMTimeMake(600 * MIN(MAX_VIDEO_DURATION, _curAsset.duration), 600);
    __weak EditVideoViewController *weakSelf = self;
    
    [self addVideoObservers];
    
    _mainQueue = [NSOperationQueue mainQueue];
    _mainQueue.maxConcurrentOperationCount = 1;
    _mainQueue.name = @"update collection view";
    
    _operationRunning = [NSMutableDictionary dictionary];
    _thumbnailCache = [NSMutableDictionary dictionary];
    
    _PtPerSecond = (SCREEN_WIDTH - 2 * THUMBNAIL_VIEW_SECTION_INSET) / 30.0f;
    
    // Create generator:
    self.generator = [[AVAssetImageGenerator alloc] initWithAsset:_avAsset];
    self.generator.appliesPreferredTrackTransform = YES;
    
    CGSize maxSize = CGSizeZero;
    CGFloat minWidth = THUMBNAIL_ITEM_WIDTH * SCREEN_SCALE;
    
    NSArray *tracks = [self.avAsset tracksWithMediaType:AVMediaTypeVideo];
    AVAssetTrack *track = [tracks firstObject];
    CGRect rect = CGRectMake(0.0f, 0.0f, track.naturalSize.width, track.naturalSize.height);
    rect = CGRectApplyAffineTransform(rect, track.preferredTransform);
    
    CGSize trackSize = rect.size;
    if (trackSize.width > trackSize.height) {
        NSInteger width = roundf(minWidth * trackSize.width / trackSize.height);
        width = (width % 2 == 0) ? width : width + 1;
        maxSize = CGSizeMake(width, minWidth);
    } else {
        NSInteger height = roundf(minWidth * trackSize.height / trackSize.width);
        height = (height % 2 == 0) ? height : height + 1;
        maxSize = CGSizeMake(minWidth, height);
    }
    
    self.generator.maximumSize = maxSize;
    
    // Create array with CMTimes of thumbnails using your own logic.
    // (Use +(NSValue*)valueWithCMTime:(CMTime)time to add CMTime in array).
    _thumbnailTimes = [self generateThumbnailTimesForVideo];
    
    if ([_thumbnailTimes count] > 0) {
        for (int i = 0; i < MIN(VIDEO_THUMBNAIL_PREFETCH_COUNT, _thumbnailTimes.count); i++) {
            [_thumbnailCache setObject:[NSNull null] forKey:_thumbnailTimes[i]];
        }
        
        // Generate thumbnail images asynchronously:
        [self.generator generateCGImagesAsynchronouslyForTimes:[_thumbnailTimes subarrayWithRange:NSMakeRange(0, MIN(VIDEO_THUMBNAIL_PREFETCH_COUNT, _thumbnailTimes.count))]
                                             completionHandler:^(CMTime requestedTime,
                                                                 CGImageRef image,
                                                                 CMTime actualTime,
                                                                 AVAssetImageGeneratorResult result,
                                                                 NSError* error)
         {
             // This block is performed for each CMTime in times array.
             if (result == AVAssetImageGeneratorSucceeded) {
                 UIImage* thumbnail = [[UIImage alloc] initWithCGImage:image];
                 NSValue *timeValue = [NSValue valueWithCMTime:requestedTime];
                 
                 [_thumbnailCache setObject:thumbnail forKey:timeValue];
                 
                 NSBlockOperation *updateView = [NSBlockOperation blockOperationWithBlock:^{
                     NSInteger index = [_thumbnailTimes indexOfObject:timeValue];
                     if (index != NSNotFound && index < _thumbnailTimes.count) {
                         NSIndexPath *indexPath = [NSIndexPath indexPathForRow:index inSection:0];
                         UICollectionViewCell *cell = [weakSelf.thumbnailCollectionView cellForItemAtIndexPath:indexPath];
                         if (cell) {
                             UIImageView *imgView = (UIImageView *)[cell.contentView viewWithTag:1002];
                             imgView.image = thumbnail;
                         }
                     }
                 }];
                 
                 [weakSelf.mainQueue addOperation:updateView];
             }
         }];
    }
    
    //            [[NSNotificationCenter defaultCenter] addObserver:self
    //                                                     selector:@selector(appWillEnterForeground:)
    //                                                         name:UIApplicationWillEnterForegroundNotification
    //                                                       object:nil];
    
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(appDidEnterBackground:)
                                                 name:UIApplicationDidEnterBackgroundNotification
                                               object:nil];
    
    
    
    dispatch_async(dispatch_get_main_queue(), ^{
        
        
        self.navTitleLabel.text = QWImagePickerLocalizedString(@"Edit video", nil);
        [self.doneBtn setTitle:QWImagePickerLocalizedString(@"Add", nil) forState:UIControlStateNormal];
        
        self.dialView = [[TRSDialView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, SCREEN_WIDTH, 40.0f)];
        self.dialView.minorTickDistance = 2 * _PtPerSecond;
        self.dialView.leadingSpace = THUMBNAIL_VIEW_SECTION_INSET;
        [self.dialView setDialRangeFrom:0 to:MAX(ceilf(self.curAsset.duration / 2), 15)];
        
        _clipView = [[SelectVideoClipView alloc] initWithFrame:CGRectMake(0.0f, THUMBNAIL_ITEM_TOP_INSET, SCREEN_WIDTH, THUMBNAIL_ITEM_WIDTH)];
        _clipView.delegate = self;
        _clipView.autoresizingMask = UIViewAutoresizingFlexibleBottomMargin;
        CGFloat maxDuration = MIN(MAX_VIDEO_DURATION, self.curAsset.duration);
        [_clipView updateViewWithMinWidth:_PtPerSecond * MIN_VIDEO_DURATION
                                 maxWidth: _PtPerSecond * maxDuration
                                   margin:THUMBNAIL_VIEW_SECTION_INSET];
        [self.footerView addSubview:_clipView];
        
        [self.collectionViewLayout setMinimumInteritemSpacing:0.0f];
        [self.collectionViewLayout setSectionInset:UIEdgeInsetsMake(THUMBNAIL_ITEM_TOP_INSET, 0.0f, 0.0f, 0.0f)];
        
        [self.thumbnailCollectionView setDataSource:self];
        [self.thumbnailCollectionView setDelegate:self];
        [self.thumbnailCollectionView setShowsHorizontalScrollIndicator:NO];
        [self.thumbnailCollectionView setShowsVerticalScrollIndicator:NO];
        [self.thumbnailCollectionView setBackgroundColor:[UIColor clearColor]];
        
        [self.thumbnailCollectionView registerClass:[UICollectionViewCell class]
                         forCellWithReuseIdentifier:@"videoThumbnailCollectionViewCell"];
        [self.thumbnailCollectionView registerClass:[UICollectionReusableView class]
                         forSupplementaryViewOfKind:UICollectionElementKindSectionHeader
                                withReuseIdentifier:@"sectionHeaderView"];
        [self.thumbnailCollectionView registerClass:[UICollectionReusableView class]
                         forSupplementaryViewOfKind:UICollectionElementKindSectionFooter
                                withReuseIdentifier:@"sectionFooterView"];
        
        self.thumbnailCollectionView.decelerationRate = UIScrollViewDecelerationRateFast;
        
        self.dialView.frame = CGRectMake(self.dialView.frame.origin.x,
                                         self.thumbnailCollectionView.frame.size.height - self.dialView.frame.size.height,
                                         self.dialView.frame.size.width,
                                         self.dialView.frame.size.height);
        self.dialView.autoresizingMask = UIViewAutoresizingFlexibleTopMargin;
        
        [self.thumbnailCollectionView addSubview:self.dialView];
        
        self.videoPlayIcon.hidden = YES;
        
        [self.videoContainerView addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(pauseVideo:)]];
        
        CALayer *viewLayer = [self.videoContainerView layer];
        [viewLayer setMasksToBounds:YES];
        
        CGRect bounds = [self.videoContainerView bounds];
        [self.playerLayer setFrame:bounds];
        
        [viewLayer insertSublayer:self.playerLayer below:self.videoPlayIcon.layer];
        [self.player play];
    });
  
    
    
}
#pragma mark -
#pragma mark helper functions

- (NSArray *)generateThumbnailTimesForVideo
{
    NSMutableArray *times = [NSMutableArray array];
    
    double interval = THUMBNAIL_ITEM_WIDTH / _PtPerSecond;

    NSInteger i = 0;
    for (double d = 0.0f; d < self.curAsset.duration; d += interval) {
        CMTime time = CMTimeMake(30 * THUMBNAIL_ITEM_WIDTH * i, SCREEN_WIDTH - 2 * THUMBNAIL_VIEW_SECTION_INSET);

        [times addObject:[NSValue valueWithCMTime:time]];
        i++;
    }

    return times;
}

- (void)addVideoObservers
{
    __weak EditVideoViewController *weakSelf = self;

    [self removeVideoObservers];

    videoProgressObserver = [_player addPeriodicTimeObserverForInterval:CMTimeMake(1, 200)
                                                                  queue:NULL
                                                             usingBlock:^(CMTime time) {
                                                                 CGFloat played = (CMTimeGetSeconds(time) - CMTimeGetSeconds(weakSelf.beginTime));
                                                                 played = MAX(0.0f, played);
                                                                 
                                                                 CGFloat total = (CMTimeGetSeconds(weakSelf.endTime) - CMTimeGetSeconds(weakSelf.beginTime));
                                                                 
                                                                 [weakSelf.clipView updatePlayProgress:played / total];
                                                             }];
    
    videoEndObserver = [_player addBoundaryTimeObserverForTimes:@[[NSValue valueWithCMTime:_endTime]]
                                                          queue:NULL
                                                     usingBlock:^{
                                                         [weakSelf.player.currentItem seekToTime:weakSelf.beginTime];
                                                     }];
}

- (void)removeVideoObservers
{
    if (videoProgressObserver) {
        [self.player removeTimeObserver:videoProgressObserver];
        videoProgressObserver = nil;
    }
    
    if (videoEndObserver) {
        [self.player removeTimeObserver:videoEndObserver];
        videoEndObserver = nil;
    }
}

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view from its nib.
    
    if ([self respondsToSelector:@selector(automaticallyAdjustsScrollViewInsets)]) {
        self.automaticallyAdjustsScrollViewInsets = NO;
        self.extendedLayoutIncludesOpaqueBars = YES;
    }
    
    self.videoPlayIcon.image = [QWImageMangerConfig imageNamed:@"button_vidoe_play_132.png"];
    [self.cancelBtn setImage:[QWImageMangerConfig imageNamed:@"nav_video_cancle_white_32.png"] forState:UIControlStateNormal];
    _toast = [[ACNavBarDrawer alloc] initWithView:self.view];
    
  
    if ([_curAsset.asset isKindOfClass:[PHAsset class]])
    {
        PHImageManager  *manger = [PHImageManager defaultManager];
        [manger requestAVAssetForVideo:(PHAsset*)_curAsset.asset
                               options:nil
                         resultHandler:^(AVAsset *asset, AVAudioMix *audioMix, NSDictionary *info) {
                             _avAsset = asset;
                             //DebugLog(@"asset:%@ audioMix:%@ info:%@",asset,audioMix,info);
                             [self handleAftergetAVAsset];
                         
                         }];
        
    }else
    {
         [self handleAftergetAVAsset];
    }



}


- (void)viewDidLayoutSubviews
{
    [super viewDidLayoutSubviews];

    CGRect bounds = [self.videoContainerView bounds];
    [self.playerLayer setFrame:bounds];
    self.videoPlayIcon.center = CGPointMake(self.videoContainerView.bounds.size.width / 2.0f, self.videoContainerView.bounds.size.height/2.0f);
}

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    
    [self.navigationController setNavigationBarHidden:YES];
    [[UIApplication sharedApplication] setStatusBarHidden:YES];
}

- (void)viewWillDisappear:(BOOL)animated
{
    [super viewWillDisappear:animated];

    [[UIApplication sharedApplication] setStatusBarHidden:NO];
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

- (void)pauseVideo:(UITapGestureRecognizer *)recg
{
    if ([self.player rate] > 0.999f) {
        [self.player pause];
        self.videoPlayIcon.hidden = NO;
        
        [self.clipView hidePlayProgressWithAnimation:YES];
    } else {
        [self.player play];
        self.videoPlayIcon.hidden = YES;
        [self.clipView showPlayPorgressWithAnimation:YES];
    }
}

- (void)appDidEnterBackground:(NSNotification *)notify
{
    [self.player pause];
    self.videoPlayIcon.hidden = NO;
    
    [self.clipView hidePlayProgressWithAnimation:NO];
}

#pragma mark - UICollectionView Datasource
- (NSInteger)collectionView:(UICollectionView *)view numberOfItemsInSection:(NSInteger)section {
    return self.thumbnailTimes.count;
}

- (NSInteger)numberOfSectionsInCollectionView: (UICollectionView *)collectionView {
    return 1;
}

- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
    if (indexPath.row + 1 < _thumbnailTimes.count) {
        return CGSizeMake(THUMBNAIL_ITEM_WIDTH, THUMBNAIL_ITEM_WIDTH);
    } else {
        double interval = THUMBNAIL_ITEM_WIDTH / _PtPerSecond;
        double remainTime = interval - (interval * _thumbnailTimes.count - self.curAsset.duration);
        return CGSizeMake(ceilf(THUMBNAIL_ITEM_WIDTH * remainTime / interval), THUMBNAIL_ITEM_WIDTH);
    }
}

- (UICollectionViewCell *)collectionView:(UICollectionView *)cv cellForItemAtIndexPath:(NSIndexPath *)indexPath {
    UICollectionViewCell *cell = [cv dequeueReusableCellWithReuseIdentifier:@"videoThumbnailCollectionViewCell"
                                                               forIndexPath:indexPath];
    cell.backgroundColor = [UIColor clearColor];
    UIImageView *imgView = (UIImageView *)[cell.contentView viewWithTag:1002];
    if (!imgView) {
        imgView = [[UIImageView alloc] initWithFrame:cell.contentView.bounds];
        imgView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
        imgView.contentMode = UIViewContentModeScaleAspectFill;
        imgView.backgroundColor = PLACEHODER_BLUE_COLOR;
        imgView.clipsToBounds = YES;
        imgView.layer.masksToBounds = YES;
        imgView.tag = 1002;

        [cell.contentView addSubview:imgView];
    }

    NSValue *timeValue = [self.thumbnailTimes objectAtIndex:indexPath.row];
    UIImage *image = [self.thumbnailCache objectForKey:timeValue];
    
    if ([image isKindOfClass:[UIImage class]]) {
        imgView.image = image;
    } else {
        imgView.image = nil;
    }
    
    if (indexPath.row == 0 && self.thumbnailTimes.count == indexPath.row + 1) {
        CAShapeLayer *clipLayer = [CAShapeLayer layer];
        UIBezierPath *clipPath = [UIBezierPath bezierPathWithRoundedRect:imgView.bounds
                                                       byRoundingCorners:UIRectCornerAllCorners
                                                             cornerRadii:CGSizeMake(3.0f, 3.0f)];
        clipLayer.path = clipPath.CGPath;
        clipLayer.frame = imgView.bounds;
        imgView.layer.mask = clipLayer;
    } else if (indexPath.row == 0) {
        CAShapeLayer *clipLayer = [CAShapeLayer layer];
        UIBezierPath *clipPath = [UIBezierPath bezierPathWithRoundedRect:imgView.bounds
                                                       byRoundingCorners:UIRectCornerTopLeft | UIRectCornerBottomLeft
                                                             cornerRadii:CGSizeMake(3.0f, 3.0f)];
        clipLayer.path = clipPath.CGPath;
        clipLayer.frame = imgView.bounds;
        imgView.layer.mask = clipLayer;
    } else if (indexPath.row + 1 == self.thumbnailTimes.count) {
        CAShapeLayer *clipLayer = [CAShapeLayer layer];
        UIBezierPath *clipPath = [UIBezierPath bezierPathWithRoundedRect:imgView.bounds
                                                       byRoundingCorners:UIRectCornerTopRight | UIRectCornerBottomRight
                                                             cornerRadii:CGSizeMake(3.0f, 3.0f)];
        clipLayer.path = clipPath.CGPath;
        clipLayer.frame = imgView.bounds;
        imgView.layer.mask = clipLayer;
    } else {
        imgView.layer.mask = nil;
    }

    return cell;
}

- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout referenceSizeForHeaderInSection:(NSInteger)section
{
    return CGSizeMake(THUMBNAIL_VIEW_SECTION_INSET, THUMBNAIL_VIEW_SECTION_INSET);
}

- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout referenceSizeForFooterInSection:(NSInteger)section
{
    return CGSizeMake(THUMBNAIL_VIEW_SECTION_INSET, THUMBNAIL_VIEW_SECTION_INSET);
}

- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath
{
    
    if ([kind isEqualToString:UICollectionElementKindSectionHeader]) {
        UICollectionReusableView *view = [collectionView dequeueReusableSupplementaryViewOfKind:kind
                                                                            withReuseIdentifier:@"sectionHeaderView"
                                                                                   forIndexPath:indexPath];
        
        view.backgroundColor = [UIColor clearColor];
        
        return view;
    } else if ([kind isEqualToString:UICollectionElementKindSectionFooter]) {
        UICollectionReusableView *view = [collectionView dequeueReusableSupplementaryViewOfKind:kind
                                                                            withReuseIdentifier:@"sectionFooterView"
                                                                                   forIndexPath:indexPath];
        
        view.backgroundColor = [UIColor clearColor];
        
        return view;
    }
    
    return nil;
}

- (void)preloadThumbnailsForCurrentVisibleCells
{
    if (_thumbnailTimes.count == [_thumbnailCache count]) {
        return;
    }

    NSArray *indexPaths = [self.thumbnailCollectionView indexPathsForVisibleItems];
    if ([indexPaths count]) {
        indexPaths = [indexPaths sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
            NSIndexPath *indexPath1 = obj1;
            NSIndexPath *indexPath2 = obj2;
            
            if (indexPath1.row == indexPath2.row) {
                return NSOrderedSame;
            } else if (indexPath1.row < indexPath2.row) {
                return NSOrderedAscending;
            } else {
                return NSOrderedDescending;
            }
        }];

        NSIndexPath *indexPath = [indexPaths firstObject];
        NSMutableArray *subTimesArr = [NSMutableArray array];

        NSInteger begin = indexPath.row;
        NSInteger maxCnt = MIN(VIDEO_THUMBNAIL_PREFETCH_COUNT / 2, _thumbnailTimes.count - begin);

        for (NSInteger i = 0; i < maxCnt; i++) {
            NSValue *timeValue = _thumbnailTimes[begin + i];
            BOOL isLoaded = ([self.thumbnailCache objectForKey:timeValue] != nil);
            if (!isLoaded) {
                [subTimesArr addObject:timeValue];
            }
        }

        for (NSInteger i = 1; begin - i >= 0 && i < VIDEO_THUMBNAIL_PREFETCH_COUNT / 2; i++) {
            NSValue *timeValue = _thumbnailTimes[begin - i];
            BOOL isLoaded = ([self.thumbnailCache objectForKey:timeValue] != nil);
            if (!isLoaded) {
                [subTimesArr addObject:timeValue];
            }
        }

        if (subTimesArr.count == 0) {
            return;
        }

        for (int i = 0; i < subTimesArr.count; i++) {
            [_thumbnailCache setObject:[NSNull null] forKey:subTimesArr[i]];
        }

        __weak EditVideoViewController *weakSelf = self;
        // Generate thumbnail images asynchronously:
        [self.generator generateCGImagesAsynchronouslyForTimes:subTimesArr
                                             completionHandler:^(CMTime requestedTime,
                                                                 CGImageRef image,
                                                                 CMTime actualTime,
                                                                 AVAssetImageGeneratorResult result,
                                                                 NSError* error)
         {
             // This block is performed for each CMTime in times array.
             if (result == AVAssetImageGeneratorSucceeded) {
                 UIImage* thumbnail = [[UIImage alloc] initWithCGImage:image];
                 NSValue *timeValue = [NSValue valueWithCMTime:requestedTime];
                 [_thumbnailCache setObject:thumbnail forKey:timeValue];
                 
                 NSBlockOperation *updateView = [NSBlockOperation blockOperationWithBlock:^{
                     NSInteger index = [_thumbnailTimes indexOfObject:timeValue];
                     if (index != NSNotFound && index < _thumbnailTimes.count) {
                         NSIndexPath *indexPath = [NSIndexPath indexPathForRow:index inSection:0];
                         UICollectionViewCell *cell = [weakSelf.thumbnailCollectionView cellForItemAtIndexPath:indexPath];
                         if (cell) {
                             UIImageView *imgView = (UIImageView *)[cell.contentView viewWithTag:1002];
                             imgView.image = thumbnail;
                         }
                     }
                 }];
                 
                 [weakSelf.mainQueue addOperation:updateView];
             }
         }];
    }
}

- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
    CGFloat colOffsetX = self.thumbnailCollectionView.contentOffset.x;

    CGFloat offsetStartX = self.clipView.currentStartX;
    CGFloat startTime = (colOffsetX + offsetStartX) / _PtPerSecond;
    
    [self.player seekToTime:CMTimeMake(600 * startTime, 600)];
}

- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
    self.videoPlayIcon.hidden = YES;

    [self.player pause];

    [self.player.currentItem seekToTime:self.beginTime];
    [self.clipView updatePlayProgress:0.0f];

    [self removeVideoObservers];
}

- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
{
    if (!decelerate) {
        [self preloadThumbnailsForCurrentVisibleCells];

        [self resetBeginAndEndTime:@"1"];
        [self.player play];
        
        [self.clipView showPlayPorgressWithAnimation:YES];
    }
}

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
    [self preloadThumbnailsForCurrentVisibleCells];

    [self resetBeginAndEndTime:@"2"];
    [self.player play];
    
    [self.clipView showPlayPorgressWithAnimation:YES];
}

- (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView
{
    [self preloadThumbnailsForCurrentVisibleCells];
}

#pragma mark -
#pragma mark SelectVideoClipViewDelegate

- (void)resetBeginAndEndTime:(NSString *)debugAddress
{
    CGFloat offsetStartX = self.clipView.currentStartX;
    CGFloat offsetEndX = self.clipView.currentEndX;
    
    CGFloat colOffsetX = self.thumbnailCollectionView.contentOffset.x;
    
    CGFloat startTime = MAX(0.0f, (colOffsetX + offsetStartX)) / _PtPerSecond;
    CGFloat stopTime = MAX(0.0f, (colOffsetX + offsetEndX)) / _PtPerSecond;
    
    CMTime oldBeginTime = _beginTime;
    CMTime oldEndTime = _endTime;

    _beginTime = CMTimeMake(600 * startTime, 600);
    _endTime = CMTimeMake(600 * stopTime, 600);

    if (CMTIME_COMPARE_INLINE(_beginTime, !=, oldBeginTime) ||
        CMTIME_COMPARE_INLINE(_endTime, ==, oldEndTime)) {
        [self.player seekToTime:_beginTime];
    } else {
        CGFloat timeValue = CMTimeGetSeconds(_endTime) - 1.0f;
        
        [self.player seekToTime:CMTimeMake(timeValue * 600, 600)];
    }
    
    [self addVideoObservers];
}

- (void)clipViewTouchedDidBegin:(SelectVideoClipView *)view
{
    self.videoPlayIcon.hidden = YES;

    [self.player pause];
    
    [self.player.currentItem seekToTime:self.beginTime];
    
    [self removeVideoObservers];
}

- (void)clipViewTouchedDidMove:(SelectVideoClipView *)view
{
    CGFloat colOffsetX = self.thumbnailCollectionView.contentOffset.x;
    
    if (view.touchedOnLeftView) {
        CGFloat offsetStartX = self.clipView.currentStartX;
        CGFloat startTime = (colOffsetX + offsetStartX) / _PtPerSecond;

        [self.player seekToTime:CMTimeMake(600 * startTime, 600)];
    } else {
        CGFloat offsetEndX = self.clipView.currentEndX;
        CGFloat stopTime = (colOffsetX + offsetEndX) / _PtPerSecond;

        [self.player seekToTime:CMTimeMake(600 * stopTime, 600)];
    }
}

- (void)clipViewTouchedDidEnd:(SelectVideoClipView *)view
{
    [self resetBeginAndEndTime:@"3"];
    [self.player play];
    
    [self.clipView showPlayPorgressWithAnimation:YES];
}

#pragma mark -
#pragma mark Bar button events

- (CGFloat)getOriginVideoSize
{
    NSArray *tracks = [self.avAsset tracks];
    AVAssetTrack * track = [tracks firstObject];
    
    CGRect rect = CGRectMake(0.0f, 0.0f, track.naturalSize.width, track.naturalSize.height);
    rect = CGRectApplyAffineTransform(rect, track.preferredTransform);
    CGFloat realHeight = roundf(640.0f * rect.size.height / rect.size.width);
    
    CGFloat realBitRate = [[QWImageMangerConfig shareInsatnce] highVideoBitRate] / (640.0f / realHeight);
    
    CMTimeRange range = CMTimeRangeFromTimeToTime(_beginTime, _endTime);
    CGFloat resultDuration = CMTimeGetSeconds(range.duration);
    
    CGFloat estimatedSize = realBitRate * resultDuration;
    
    return estimatedSize / 8;
}

- (CGFloat)getCopmressVideoSize
{
    NSArray *tracks = [self.avAsset tracks];
    AVAssetTrack * track = [tracks firstObject];

    CGRect rect = CGRectMake(0.0f, 0.0f, track.naturalSize.width, track.naturalSize.height);
    rect = CGRectApplyAffineTransform(rect, track.preferredTransform);
    CGFloat realHeight = roundf(640.0f * rect.size.height / rect.size.width);

    CGFloat realBitRate = [[QWImageMangerConfig shareInsatnce] normalVideoBitRate] / (640.0f / realHeight);
    
    CMTimeRange range = CMTimeRangeFromTimeToTime(_beginTime, _endTime);
    CGFloat resultDuration = CMTimeGetSeconds(range.duration);

    CGFloat estimatedSize = realBitRate * resultDuration;

    return estimatedSize / 8;
}

- (NSString *)getFormattedSizeString:(CGFloat)size
{
    NSString *result = @"";
    if (size < 1024) {
        result = [NSString stringWithFormat:@"%.2fKB", size];
    } else if (size < 1024 * 1024) {
        result = [NSString stringWithFormat:@"%.0fKB", size / 1024];
    } else {
        result = [NSString stringWithFormat:@"%.0fMB", size / 1024 / 1024];
    }

    return result;
}

- (IBAction)cancelButtonPressed:(id)sender {
    [self dismissViewControllerAnimated:YES completion:nil];
}

- (IBAction)doneButtonPressed:(id)sender {
    CGFloat orgSize = [self getOriginVideoSize];
    CGFloat comSize = [self getCopmressVideoSize];

    if (orgSize > comSize + 1024 * 1024) {
        NSString *orginSzStr = [self getFormattedSizeString:[self getOriginVideoSize]];
        NSString *compresStr = [self getFormattedSizeString:[self getCopmressVideoSize]];
        
        orginSzStr = [NSString stringWithFormat:QWImagePickerLocalizedString(@"HD video(about %@)", nil), orginSzStr];
        compresStr = [NSString stringWithFormat:QWImagePickerLocalizedString(@"Normal video(about %@)", nil), compresStr];
        
        UIActionSheet *sheet = [[UIActionSheet alloc] initWithTitle:nil
                                                           delegate:self
                                                  cancelButtonTitle:QWImagePickerLocalizedString(@"Cancel", nil)
                                             destructiveButtonTitle:nil
                                                  otherButtonTitles:compresStr, orginSzStr, nil];
        
        [sheet showInView:self.view];
    } else {
        [self startProccessVideoShouldCompress:NO];
    }
}

- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
{
    if (buttonIndex == actionSheet.firstOtherButtonIndex) {
        [self startProccessVideoShouldCompress:YES];
    }
    else if (buttonIndex == actionSheet.firstOtherButtonIndex + 1) {
        [self startProccessVideoShouldCompress:NO];
    }
}

#pragma mark -
#pragma mark EditVideoHelpersDelegate

- (void)startProccessVideoShouldCompress:(BOOL)compress
{
    MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:self.view animated:YES];
    hud.customView = [MBProgressHUD getCustomSpinner];
    hud.mode = MBProgressHUDModeCustomView;
    hud.labelText = QWImagePickerLocalizedString(@"Compressing video...", nil);
    
    [self.player pause];
    [self.clipView hidePlayProgressWithAnimation:NO];

    CMTimeRange range = CMTimeRangeFromTimeToTime(_beginTime, _endTime);
    _trimVideoHelper = [[EditVideoHelpers alloc] initWithAVAsset:self.avAsset
                                                       timeRange:range
                                                            isHD:!compress];
    _trimVideoHelper.delegate = self;
    [self showProgressView];
     [_trimVideoHelper startTrimVideo];
}

- (void)trimVideoSuccessfully:(BOOL)success
                       cancel:(BOOL)cancelled
                    outputURL:(NSURL *)outputUrl
                    videoUUID:(NSString *)videoUUID
                    withError:(NSError *)error
{
    [MBProgressHUD hideAllHUDsForView:self.view animated:YES];

    if (cancelled) {
        return;
    }

    if (!success) {
        [self.toast showToastWithType:QWToastError Title:[error localizedDescription]];
        return;
    }

    __block UIImage *thumbnail = nil;
    dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        AVAsset *outputAsset = [AVAsset assetWithURL:outputUrl];

        AVAssetImageGenerator *gen = [[AVAssetImageGenerator alloc] initWithAsset:outputAsset];
        gen.appliesPreferredTrackTransform = YES;
        CMTime time = CMTimeMakeWithSeconds(0.0, 600);
        CGImageRef image = [gen copyCGImageAtTime:time actualTime:nil error:nil];
        thumbnail = [[UIImage alloc] initWithCGImage:image];
        CGImageRelease(image);
    });

     NSDictionary *infoDict = nil;
    if ([_curAsset.asset isKindOfClass:[AVAsset class]])
    {
        infoDict = @{@"isVideo":@"YES",
                     @"videoPath":[outputUrl path],
                     @"videoFileName":[outputUrl lastPathComponent],
                     @"videoThumbnail":thumbnail,
                     @"assetUrl":_curAsset.assetIdentifier,
                     @"imageAsset":_curAsset,
                     @"videoUUID":(videoUUID ? videoUUID : @"")};
    } else {
        AVURLAsset *urlasste = (AVURLAsset*)_avAsset;
        infoDict = @{@"isVideo":@"YES",
                     @"videoPath":[outputUrl path],
                     @"videoFileName":[outputUrl lastPathComponent],
                     @"videoThumbnail":thumbnail,
                     @"assetUrl":urlasste.URL,
                     @"imageAsset":_curAsset,
                     @"videoUUID":(videoUUID ? videoUUID : @"")};
    }

    [self dismissViewControllerAnimated:NO completion:^{
        if ([self.delegate respondsToSelector:@selector(didFinishEditVideoWithInfoDict:)]) {
            [self.delegate didFinishEditVideoWithInfoDict:infoDict];
        }
    }];
}

- (void)showProgressView
{
    if (!self.progressView) {
        CGFloat startY = CGRectGetMinY(self.footerView.frame);
        self.progressView = [[UIView alloc] initWithFrame:CGRectMake(0.0f, startY, 0.0f, 2.0f)];
        self.progressView.backgroundColor = [UIColor whiteColor];
    }

    [self.view addSubview:self.progressView];

//    if (!_compressLabel) {
//        CGFloat centerY = CGRectGetMinY(self.footerView.frame) - 18.0f;
//
//        _compressLabel = [[UILabel alloc] initWithFrame:CGRectMake(0.0f, 0.0f, SCREEN_WIDTH, 20.0f)];
//        _compressLabel.textColor = [UIColor colorWithWhite:1.0f alpha:0.8f];
//        _compressLabel.font = CUSTOM_FONT_LIGHT(12.0f);
//        _compressLabel.text = QWImagePickerLocalizedString(@"Compressing video...", nil);
//        _compressLabel.backgroundColor = [UIColor clearColor];
//        [_compressLabel sizeToFit];
//        
//        _compressLabel.center = CGPointMake(SCREEN_WIDTH / 2.0f, centerY);
//    }
//
//    [self.view addSubview:self.compressLabel];
//    
//    self.view.userInteractionEnabled = NO;
}

- (void)trimVideoDidUpdateProgress:(double)progress
{
    self.progressView.frame = CGRectMake(0.0f,
                                         self.progressView.frame.origin.y,
                                         SCREEN_WIDTH * progress,
                                         2.9f);
}

@end